﻿using System;
using System.Collections;
using System.Linq;
using System.Collections.Generic;

namespace Stimulus360.Services
{
    /// <summary>
    ///     This is a helper class  used for pagination.
    /// </summary>
    /// <typeparam name="T">
    ///     Object type to be converted into a Paginated List 
    /// </typeparam>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification ="Represents a Pagination enabled Collection of Entities.")]
    public class PaginatedCollection<T> :IEnumerable<T>
    {

        /// <summary>
        ///     The current page index
        /// </summary>
        public int PageIndex { get; private set; }
       
        /// <summary>
        ///     Total number of elements shown on a page
        /// </summary>
        public int PageSize { get; private set; }
        
        /// <summary>
        ///     Total number of elements
        /// </summary>
        public int TotalCount { get; private set; }
        
        /// <summary>
        ///     Total number of pages
        /// </summary>
        public int TotalPages { get; private set; }

        /// <summary>
        ///     The List of entities to be paginated
        /// </summary>
        private readonly List<T> _list = new List<T>();

        
        /// <summary>
        ///     Bool representing if this is the first page
        /// </summary>
        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 0);
            }
        }

        /// <summary>
        ///     Bool representing if this is the last page
        /// </summary>
        public bool HasNextPage
        {
            get
            {
                return (PageIndex + 1 < TotalPages);
            }
        }
        
        /// <summary>
        ///   Default Constructor  
        /// </summary>
        public PaginatedCollection()
        {
            
        }

        /// <summary>
        ///     Method to convert the list of objects into a paginated list for supporting pagination
        /// </summary>
        /// <param name="source">
        ///     List of objects to be paginated
        /// </param>
        /// <param name="pageIndex">
        ///     The page number to be displayed
        /// </param>
        /// <param name="pageSize">
        ///     No of elements to be displayed per page.
        /// </param>
        public PaginatedCollection(IQueryable<T> source, int pageIndex, int pageSize)
        {
            try
            {
                int internalPageIndex = 0;
                if(pageIndex>0)
                {
                    internalPageIndex = pageIndex - 1;
                }
                PageIndex = pageIndex;
                PageSize = pageSize;
                TotalCount = source.Count();
                TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
                _list.AddRange(source.Skip(internalPageIndex * PageSize).Take(PageSize));
            }
            catch (Exception )
            {
                throw ;
            }
        }


        #region IEnumerable<T> Members

        /// <summary>
        ///     Implements the generic IEnumerator interface to return the list enumerator
        /// </summary>
        /// <returns>
        ///     The list enumerator
        /// </returns>
        public IEnumerator<T> GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        /// <summary>
        ///     Implements the  IEnumerator interface to return the list enumerator
        /// </summary>
        /// <returns>
        ///     The list enumerator
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        #endregion
    }
}
